#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/irq.h>
#include <linux/gpio.h>



static struct device_node *np;

int irq_num;
unsigned int irq_domain;
struct irq_data *my_irq_data;
u32 my_irq_type;

// 平台设备探测函数
// 当系统检测到一个平台设备与该驱动程序匹配时，该 函数将被调用以初始化和配置设备。  
int my_platform_probe(struct platform_device *pdev)
{
    int ret = 0;

    printk(KERN_EMERG "my_platform_probe: Probing platform device!\n");
    /* 设备特定操作 */
    np = of_find_node_by_name(NULL, "myirq");
    if (! np)
    {
        printk(KERN_EMERG "Failed to find 'myirq' node\n");
        ret =  -ENODEV; // 设备不存在
        goto err_out;
    }
    printk(KERN_EMERG "device_node is : %s\n", np->name);

    // gpio转换为中断号
    irq_num = gpio_to_irq(112);
    if (irq_num < 0) {
        printk(KERN_ERR "gpio_to_irq failed (err=%d)\n", irq_num);
        ret = irq_num; // 直接返回错误码
        goto err_put_node;
    }
    printk(KERN_EMERG "gpio_to_irq is %d \n", irq_num);

    /* 获取平台设备的中断号 */
    irq_num = platform_get_irq(pdev, 0);
    if (irq_num < 0) {
        printk(KERN_ERR "platform_get_irq failed (err=%d)\n", irq_num);
        ret = irq_num; // 直接返回错误码
        goto err_put_node;
    }
    printk(KERN_EMERG "platform_get_irq is %d \n", irq_num);


    /* 从设备节点获取中断号 */
    irq_num = of_irq_get(np, 0);
    if (irq_num < 0) {
        printk(KERN_ERR "of_irq_get failed (err=%d)\n", irq_num);
        ret = irq_num; // 直接返回错误码
        goto err_put_node;
    }
    printk(KERN_EMERG "of_irq_get is %d \n", irq_num);

    /* 解析并映射中断号 */
    irq_domain =  irq_of_parse_and_map(np, 0);
    if (! irq_domain)
    {
         printk(KERN_ERR "irq_of_parse_and_map failed\n");
        ret = -EINVAL; // 无效参数
        goto err_put_node;
    }
    printk(KERN_EMERG "irq_of_parse_and_map is %d \n", irq_domain);

    /* 获取中断数据结构 */
    my_irq_data = irq_get_irq_data(irq_num);
    if (IS_ERR(my_irq_data))
    {
        printk(KERN_EMERG "irq_get_irq_data error \n");
        ret = PTR_ERR(my_irq_data);
        goto err_put_node;
    }
    /* 获取中断触发类型*/
    my_irq_type =  irq_get_trigger_type(irq_num);
    printk(KERN_EMERG "irq_get_trigger_type is 0x%X \n", my_irq_type);

    return 0;

err_put_node:
    of_node_put(np); // 减少引用计数
    np = NULL;
err_out:
    return ret;
}

// 平台设备移除函数
// 当平台设备从系统中移除时，该函数将被调用以执行 清理和释放资源的操作。
int my_platform_remove(struct platform_device *pdev)
{
    printk(KERN_EMERG "my_platform_remove: Remove platform device!\n");
    /* 设备特定操作 */
    // 释放资源（如果有）
    if (np) {
        of_node_put(np); // 减少设备树节点的引用计数
        np = NULL;
    }
    return 0;
}

// 平台设备关闭函数
// 当系统关闭时，该函数将被调用以执行与平台设备 相关的关闭操作。 
void my_platform_shutdown(struct platform_device *pdev)
{
    printk(KERN_EMERG "my_platform_shutdown: Shutdown platform device!\n");
    /* 设备特定操作 */

    
}
// 平台设备挂起函数
// 当系统进入挂起状态时，该函数将被调用以执行与 平台设备相关的挂起操作。
int my_platform_suspend(struct platform_device *pdev, pm_message_t state)
{
    printk(KERN_EMERG "my_platform_suspend: Suspend platform device!\n");
    /* 设备特定操作 */

    return 0;
}
// 平台设备恢复函数
// 当系统从挂起状态恢复时，该函数将被调用以执行与 平台设备相关的恢复操作。  
int my_platform_resume(struct platform_device *pdev)
{
    printk(KERN_EMERG "my_platform_resume: Resume platform device!\n");
    /* 设备特定操作 */

    return 0;
}


const struct of_device_id of_match_table_id[] = {
    {.compatible = "my device_tree irq"},
    {},
};


static struct platform_driver my_platform_driver = {
    .probe = my_platform_probe,
    .remove = my_platform_remove,
    .shutdown = my_platform_shutdown,
    .suspend = my_platform_suspend,
    .resume = my_platform_resume,

    .driver = {
        .name = "my_platform_GPIO",
        .owner = THIS_MODULE,
        .of_match_table = of_match_table_id,
    },
};


static int __init my_platform_device_init(void)
{   
    int ret;

    // 注册平台驱动
    ret = platform_driver_register(&my_platform_driver);
     if (ret < 0)
    {
        printk(KERN_EMERG "Failed platform_driver_register.\n");
        return ret;
    }

    printk(KERN_EMERG "platform_driver_register OK!\n");

    return 0;
}



static void __exit my_platform_device_exit(void)
{
    platform_driver_unregister(&my_platform_driver);// 注销平台驱动
    printk(KERN_EMERG "platform_driver_unregister OK!\n");
}



module_init(my_platform_device_init);
module_exit(my_platform_device_exit);

MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Treasure1029");










